﻿ #region Disclaimer/Info
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
 //
 //   File:		UrlBuilderBase.cs
 //   Website:		http://dexterblogengine.com/
 //   Authors:		http://dexterblogengine.com/About.ashx
 //   Rev:		1
 //   Created:		19/01/2011
 //   Last edit:		19/01/2011
 //   License:		GNU Library General Public License (LGPL)
 // 
 //   For updated news and information please visit http://dexterblogengine.com/
 //   Dexter is hosted to Codeplex at http://dexterblogengine.codeplex.com
 //   For any question contact info@dexterblogengine.com
 //
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #endregion

using System;
using System.Web;
using System.Web.Mvc;
using Dexter.CallContext;
using Dexter.DataTransferObject;
using Dexter.Domain.Model;
using Dexter.Logger.Contracts;
using Topics.Radical.Validation;

namespace Dexter.Services.Implementation {
	/// <summary>
	/// 	The implementation of <see cref = "IUrlBuilderBase" />.
	/// </summary>
	public class UrlBuilderBase : IUrlBuilderBase {
		const string DOMAIN_KEY = "DOMAIN_SESSION_CURRENT";
		protected readonly IConfigurationService ConfigurationService;
		protected readonly IDexterContext DexterContext;
		protected readonly ILogger Logger;

		/// <summary>
		/// Initializes a new instance of the <see cref="UrlBuilderBase"/> class.
		/// </summary>
		/// <param name="logger">The logger.</param>
		/// <param name="dexterContext">The dexter context.</param>
		/// <param name="configurationService">The configuration service.</param>
		public UrlBuilderBase ( ILogger logger , IDexterContext dexterContext , IConfigurationService configurationService ) {
			this.Logger = logger;
			this.DexterContext = dexterContext;
			this.ConfigurationService = configurationService;
		}

		#region Implementation of IUrlBuilderRoot

		/// <summary>
		/// 	Gets the home page <see cref = "Uri" />.
		/// </summary>
		/// <value></value>
		/// <example>
		/// 	http://dexterblogengine.com
		/// </example>
		public virtual Uri HomePage {
			get {
				var configuraton = ConfigurationService.Configuration;

				var siteWithHttp = new Uri ( string.Format ( "http{1}://{0}/" , configuraton.UrlBuilder.SiteDomain , configuraton.UrlBuilder.ForceHttps
				                                                                                                     	? "s"
				                                                                                                     	: string.Empty ) );
				try {
					if (DexterContext.Context != null) {
						Logger.Debug ( "Getting uri in webcontext." );

						if (DexterContext.Context.Items[DOMAIN_KEY] == null) {
							Logger.Debug ( "Creating new SiteWithHttp Uri in webcontext." );

							string baseUri = string.Format ( "http{1}://{0}/", DexterContext.Context.Request.Url.Authority, configuraton.UrlBuilder.ForceHttps
							                                                                                        	? "s"
							                                                                                        	: string.Empty );

							DexterContext.Context.Items[ DOMAIN_KEY ] = new Uri ( baseUri );
						}
						else {
							Logger.Debug ( "SiteWithHttp Uri already in webcontext." );
						}

						return ( Uri )DexterContext.Context.Items[DOMAIN_KEY];
					}

					Logger.Debug ( "Getting SiteWithHttp Uri from default value." );

					return siteWithHttp;
				}
				catch ( HttpException ) {
					//this catch is used because in IIS7.x and Integrated mode could be generate an error
					//see here for more into http://mvolo.com/blogs/serverside/archive/2007/11/10/Integrated-mode-Request-is-not-available-in-this-context-in-Application_5F00_Start.aspx

					Logger.Warn ( "Getting SiteWithHttp Uri from default value becouse and httpexception has occurred." );

					return siteWithHttp;
				}
			}
		}

		/// <summary>
		/// 	Gets the pingback url.
		/// </summary>
		/// <value></value>
		/// <example>
		/// 	http://dexterblogengine.com/pingback.axd
		/// </example>
		public virtual string PingBackUrl {
			get { return ToCaseConfiguration ( new Uri ( HomePage , "pingback.axd" ) ); }
		}

		/// <summary>
		/// 	Gets the feed url.
		/// </summary>
		/// <value></value>
		/// <example>
		/// 	http://dexterblogengine.com/feed/rss
		/// </example>
		public virtual string FeedUrl {
			get { return ToCaseConfiguration ( new Uri ( HomePage , "Feed/Rss/" ) ); }
		}

		/// <summary>
		/// 	Gets the MetaWeblog handler url.
		/// </summary>
		/// <value></value>
		/// <example>
		/// 	http://dexterblogengine.com/metaweblog.axd
		/// </example>
		public virtual string MetaWeblogApi {
			get { return ToCaseConfiguration ( new Uri ( HomePage , "MetaWeblog.axd" ) ); }
		}

		/// <summary>
		/// 	Gets the meta weblog RSD url.
		/// </summary>
		/// <value></value>
		/// <example>
		/// 	http://dexterblogengine.com/metarsd
		/// </example>
		public virtual string MetaWeblogRsd {
			get { return ToCaseConfiguration ( new Uri ( HomePage , "Feed/Rsd/" ) ); }
		}

		/// <summary>
		/// 	Gets the open search.
		/// </summary>
		/// <value>The open search.</value>
		public virtual string OpenSearch {
			get { return ToCaseConfiguration ( new Uri ( HomePage , "/Home/OpenSearch/" ) ); }
		}

		/// <summary>
		/// 	Gets the search page.
		/// </summary>
		/// <value>The open search.</value>
		/// <example>
		/// 	http://dexterblogengine.com/Search/
		/// </example>
		public virtual string SearchHome {
			get { return ToCaseConfiguration ( new Uri ( HomePage , "Search" ) ); }
		}

		/// <summary>
		/// 	Gets the search page.
		/// </summary>
		/// <value>The open search.</value>
		/// <example>
		/// 	http://dexterblogengine.com/Contact/
		/// </example>
		public string ContactHome {
			get { return ToCaseConfiguration ( new Uri ( HomePage, "Contact" ) ); }
		}

		/// <summary>
		/// 	Gets the favicon url.
		/// </summary>
		/// <value></value>
		/// <example>
		/// 	http://dexterblogengine.com/images/favicon.ico
		/// </example>
		public virtual string Favicon {
			get { return ToCaseConfiguration ( new Uri ( HomePage , "Images/favicon.ico" ) ); }
		}

		/// <summary>
		/// 	Gets the last comments page url.
		/// </summary>
		/// <value></value>
		/// <example>
		/// 	http://dexterblogengine.com/lastcomments
		/// </example>
		public virtual string LastComments {
			get { throw new NotImplementedException ( ); }
		}

		/// <summary>
		/// 	Gets the trackback url.
		/// </summary>
		/// <param name = "item"></param>
		/// <returns></returns>
		/// <example>
		/// 	http://dexterblogengine.com/trackback.axd
		/// </example>
		public virtual string TrackBackUrl ( Item item ) {
			Ensure.That ( item )
				.Named ( "item" )
				.WithPreview ( ( v , e ) => Logger.Warn ( v.GetFullErrorMessage ( ) , e ) )
				.IsNotNull ( )
				.WithMessage ( "Invalid post key." );

			return ToCaseConfiguration ( new Uri ( HomePage , "Trackback.axd?id=" + item.Id ) );
		}

		/// <summary>
		/// 	Gets the trackback url.
		/// </summary>
		/// <example>
		/// 	http://dexterblogengine.com/trackback.axd
		/// </example>
		public string TrackBackUrl ( PostLightDto item ) {
			Ensure.That ( item )
				.Named ( "item" )
				.WithPreview ( ( v, e ) => Logger.Warn ( v.GetFullErrorMessage ( ), e ) )
				.IsNotNull ( )
				.WithMessage ( "Invalid post key." );

			return ToCaseConfiguration ( new Uri ( HomePage, "Trackback.axd?id=" + item.Id ) );
		}

		/// <summary>
		/// 	Gets the search page url.
		/// </summary>
		/// <param name = "keyword">The keyword.</param>
		/// <returns></returns>
		/// <example>
		/// 	http://dexterblogengine.com/search/keyword
		/// </example>
		public virtual string Search ( string keyword ) {
			throw new NotImplementedException ( );
		}

		/// <summary>
		/// 	Resolves the URL.
		/// </summary>
		/// <param name = "value">The value.</param>
		/// <returns></returns>
		public virtual string ResolveUrl ( string value ) {
			if ( value == null ) {
				return null;
			}

			// *** Absolute path - just return
			if ( value.IndexOf ( "://" ) != -1 ) {
				return value;
			}

			// *** Fix up image path for ~ root app dir directory
			if ( value.StartsWith ( "~" ) ) {
				return VirtualPathUtility.ToAbsolute ( value );
			}

			return value;
		}

		/// <summary>
		/// Gets the log on.
		/// </summary>
		/// <value>The log on.</value>
		public string LogOn {
			get { return ToCaseConfiguration ( new Uri ( HomePage, "Admin/Login/" ) ); }
		}

		/// <summary>
		/// Gets the log off.
		/// </summary>
		/// <value>The log off.</value>
		public string LogOff {
			get { return ToCaseConfiguration ( new Uri ( HomePage, "Admin/Login/LogOff/" ) ); }
		}

		/// <summary>
		/// Add the specified page to the specified url;
		/// </summary>
		/// <param name="pageIndex">Index of the page.</param>
		/// <param name="viewContext">The view context.</param>
		/// <returns></returns>
		public virtual string SetPageToUrl (int pageIndex, ViewContext viewContext  ) {

			var areaName = viewContext.RouteData.DataTokens["area"] as string;

			var action = viewContext.Controller.ValueProvider.GetValue ( "action" );
			var controller = viewContext.Controller.ValueProvider.GetValue ( "controller" );
			var id = viewContext.Controller.ValueProvider.GetValue ( "id" );

			string u;

			//TODO: this piece of code is horrible. It must be changed
			if (controller.RawValue.ToString (  ).ToLowerInvariant (  ) == "blog" && action.RawValue.ToString ( ).ToLowerInvariant ( ) == "archive") {
				var year = viewContext.Controller.ValueProvider.GetValue ( "year" );
				var month = viewContext.Controller.ValueProvider.GetValue ( "month" );
				u = string.Format ( "{0}/{1}/{2}/{3}/{4}/Page/{5}" , areaName , controller.RawValue , action.RawValue , year.RawValue , month.RawValue , pageIndex );
			}
			else if(id != null) {
				u = string.Format ( "{0}/{1}/{2}/{3}/Page/{4}", areaName, controller.RawValue, action.RawValue,id.RawValue, pageIndex );
			}
			else {
				u = string.Format ( "{0}/{1}/{2}/Page/{3}", areaName, controller.RawValue, action.RawValue, pageIndex );
			}

			

			return ToCaseConfiguration ( new Uri ( HomePage, u ) );
		}

		/// <summary>
		/// 	Return the url for the combined styles route
		/// </summary>
		/// <example>
		/// 	http://dexterblogengine.com/resources/style/yourkey/
		/// </example>
		public virtual string StylesheedCombinedUrl ( string key ) {
			var relativeUrl = string.Format ( "Resources/Css/{0}" , key );
			return new Uri ( HomePage , relativeUrl ).ToString ( );
		}

		/// <summary>
		/// 	Return the url for the combined javascript route
		/// </summary>
		/// <example>
		/// 	http://dexterblogengine.com/resources/js/yourkey/
		/// </example>
		public virtual string JavascriptCombinedUrl ( string key ) {
			var relativeUrl = string.Format ( "Resources/Js/{0}" , key );
			return new Uri ( HomePage , relativeUrl ).ToString ( );
		}

		#endregion

		protected string ToCaseConfiguration ( Uri url ) {
			return ToCaseConfiguration ( url.ToString ( ) );
		}

		protected string ToCaseConfiguration ( string value ) {
			var configuration = ConfigurationService.Configuration;
			switch ( configuration.UrlBuilder.UrlCase ) {
				case UrlCase.Lower:
					return value.ToLower ( ).EncodeUrl ( );
				case UrlCase.UpperCase:
					return value.ToUpper ( ).EncodeUrl ( );
				default:
					return value.EncodeUrl ( );
			}
		}
	}
}
